﻿using System;
using System.Runtime.InteropServices;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace GLSL
{
    public class VertexBufferObject
    {
        private int _id;
        private int _length;
        private BeginMode _drawmode;

        public VertexBufferObject()
        {
            GraphicsContext.Assert();
            GL.Arb.GenBuffers(1, out this._id);
            if (this._id == 0)
                throw new Exception("Could not create VBO.");

            Console.WriteLine("#VBO Created: " + this._id);
        }

        public VertexBufferObject(Vertex[] data)
        {
            this.SetData(data);
        }

        public void setDrawMode(BeginMode DrawMode)
        {
            this._drawmode = DrawMode;
        }

        public void startQuads()
        {
            this._drawmode = BeginMode.Quads;
        }

        public void SetData(Vertex[] data)
        {
            int num = 0;
            if (data != null)
            {
                this._length = (int)data.Length;
                GL.Arb.BindBuffer(BufferTargetArb.ArrayBuffer, this._id);
                GL.Arb.BufferData<Vertex>(BufferTargetArb.ArrayBuffer, new IntPtr(this._length * Vertex.Stride), data, BufferUsageArb.StaticDraw);
                GL.Arb.GetBufferParameter(ArbVertexBufferObject.ArrayBufferArb, BufferParameterNameArb.BufferSize, out num);
                if (num == this._length * Vertex.Stride)
                {
                    return;
                }
                else
                {
                    throw new Exception("VBO data corruption");
                }
            }
            else
            {
                throw new ArgumentNullException("data");
            }
        }

        public void Render()
        {
            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.NormalArray);
            GL.EnableClientState(ArrayCap.TextureCoordArray);

            GL.BindBuffer(BufferTarget.ArrayBuffer, this._id);

            GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride, new IntPtr(0));
            GL.TexCoordPointer(2, TexCoordPointerType.Float, Vertex.Stride, new IntPtr(12));
            GL.NormalPointer(NormalPointerType.Float, Vertex.Stride, new IntPtr(20));
            
            
            GL.DrawArrays(BeginMode.Quads, 0, this._length);

            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

            GL.DisableClientState(ArrayCap.VertexArray);
            GL.DisableClientState(ArrayCap.NormalArray);
            GL.DisableClientState(ArrayCap.TextureCoordArray);       
        }

        public void Destroy()
        {
            GL.Arb.DeleteBuffers(1, ref this._id);
        }
    }
}
